package bd;

import java.sql.*;
import javax.swing.JOptionPane;
import oracle.jdbc.OracleTypes;

/**
 * Classe conecta, encarregada de fazer a ligação com o banco de dados.
 * Nessa classe há também alguns tratamentos de exceção quando são feitas
 * inserções, remoções, atualizações, manipulação(chamadas) de procedimentos, etc.
 */
public class conecta {

    private Connection conexao;
    private Statement stmt;

    /**
     * Construtor da classe conecta. É encarregado de fazer a conexão com o banco de dados
     * Para isso recebe o endereço do banco, assim como um login e senha.
     * Também faz tratamento de erro quando uma conexão não pode ser estabelecida
     */
    public conecta() throws ClassNotFoundException, SQLException {

        Class.forName("oracle.jdbc.driver.OracleDriver");

        try {
            conexao = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "a6793292", "a6793292");

            conexao.setAutoCommit(false);
            stmt = conexao.createStatement();
            stmt.execute("ALTER SESSION SET deferred_segment_creation = FALSE");
            JOptionPane.showMessageDialog(null, "Banco conectado");

        } catch (Exception p) {
            JOptionPane.showMessageDialog(null, "Não foi possível se conectar ao servidor!");
        }
    }

    /** Executa uma busca no banco de dados e retorna o ResultSet resultados
     *
     */
    public ResultSet consulta(String sql) throws SQLException {

        ResultSet resultados = getStmt().executeQuery(sql);

        return resultados;
    }

    /** Executa uma inserção feita no banco de dados.
     * Trava erros de inserção. Em caso de sucesso, retorna uma mensagem de confirmação.
     */
    public void insercao(String sql) {
        try {
            getStmt().execute(sql);
            getStmt().execute("commit");
            JOptionPane.showMessageDialog(null, "Inserção feita com sucesso!");
        } catch (SQLException ex) {
            trataErro(ex);
        }
    }

    /**
     * Pega uma conexão
     */
    public Connection getConexao() {
        return conexao;
    }

    /**
     * Seta uma conexão com determinado valor
     */
    public void setConexao(Connection conn) {
        this.conexao = conn;
    }

    public Statement getStmt() {
        return stmt;
    }

    public void setStmt(Statement stmt) {
        this.stmt = stmt;
    }

    /** Executa uma atualização feita no banco de dados.
     * Trata erros de atualização. Em caso de sucesso, retorna uma mensagem de confirmação.
     */
    void atualiza(String sql) {
        try {
            getStmt().execute(sql);
            getStmt().execute("commit");
            JOptionPane.showMessageDialog(null, "Atualização feita com sucesso!");
        } catch (SQLException ex) {
            trataErro(ex);
        }
    }

    /** Executa uma remoção feita no banco de dados.
     * Trata erros de remoção. Em caso de sucesso, retorna uma mensagem de confirmação.
     */
    void remove(String sql) {
        try {
            getStmt().execute(sql);
            getStmt().execute("commit");
            JOptionPane.showMessageDialog(null, "Remoção feita com sucesso!");
        } catch (SQLException ex) {
            trataErro(ex);
        }
    }

    /** Executa um procedimento feita no banco de dados.
     * Trata erros na execução do procedimento. Em caso de sucesso, retorna uma mensagem de confirmação.
     */
    void executarProcedimento(String sql) {
        try {
            getStmt().execute(sql);//colocar commit no final do procedimento
            JOptionPane.showMessageDialog(null, "Procedimento executado com suceosso!");
        } catch (SQLException ex) {
            trataErro(ex);
        }
    }

    /** Método que recebe determinado tipo de erro e retorna uma mensagem
     */
    protected void trataErro(SQLException ex) {
        String erro = ex.toString();
        erro = erro.substring(34, erro.length());
        JOptionPane.showMessageDialog(null, "Ocorreu um erro de \"" + erro + "\"");
    }

    /** Método encarregado de chamar os procedimentos
     *
     */
    public ResultSet chamaProcedimento(String sql, String argumento) throws SQLException {
        CallableStatement stmtC;
        stmtC = conexao.prepareCall(sql);
        stmtC.registerOutParameter(1, OracleTypes.CURSOR);
        stmtC.setString(2, argumento);
        stmtC.execute();
        return (ResultSet) stmtC.getObject(1);
    }
}
